package com.hfzy.ihk.web.aliyuncall.controller;

import com.alibaba.fastjson.JSONObject;
import com.aliyuncs.DefaultAcsClient;
import com.aliyuncs.IAcsClient;
import com.aliyuncs.dyvmsapi.model.v20170525.CancelCallRequest;
import com.aliyuncs.dyvmsapi.model.v20170525.CancelCallResponse;
import com.aliyuncs.dyvmsapi.model.v20170525.ClickToDialRequest;
import com.aliyuncs.dyvmsapi.model.v20170525.ClickToDialResponse;
import com.aliyuncs.profile.DefaultProfile;
import com.aliyuncs.profile.IClientProfile;
import com.hfzy.ihk.common.util.date.DateUtils;
import com.hfzy.ihk.common.util.string.StringTools;
import com.hfzy.ihk.common.util.string.StringUtil;
import com.hfzy.ihk.common.util.uuid.base64uuid.UUIDs;
import com.hfzy.ihk.web.aliyuncall.biz.AliyunCallStateBiz;
import com.hfzy.ihk.web.aliyuncall.biz.AliyunRecordFileBiz;
import com.hfzy.ihk.web.aliyuncall.biz.AliyunTransNumBiz;
import com.hfzy.ihk.web.aliyuncall.constant.*;
import com.hfzy.ihk.web.aliyuncall.support.SampleMemoryCache;
import com.hfzy.ihk.web.aliyuncall.support.websocket.WebSocketUtils;
import com.hfzy.ihk.web.aliyuncall.vo.AliyunTransNumVo;
import com.hfzy.ihk.web.aliyuncall.vo.CallOutVo;
import com.hfzy.ihk.web.aliyuncall.vo.InterruptVo;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ThreadLocalRandom;
import java.util.concurrent.TimeUnit;

/**
 * 系统呼叫http 控制类，中断呼叫入口等.
 */
@RestController
@RequestMapping("callCenter")
public class CallCenterController {
    private static final Logger logger = LoggerFactory.getLogger(CallCenterController.class);
    @Autowired
    RedisTemplate redisTemplate;


    @Autowired
    AliyunTransNumBiz aliyunTransNumBiz;

    @Autowired
    AliyunCallStateBiz aliyunCallStateBiz;

    @Autowired
    AliyunRecordFileBiz aliyunRecordFileBiz;

    @Autowired
    WebSocketUtils webSocketUtils;

    @RequestMapping("/interruptCall")
    @ResponseBody
    public String interruptCall(String sessionId, boolean autoInterrupt, String jsonpCallBack) {

        logger.debug("-----------interruptCall------------:" + sessionId + " isAuto:" + autoInterrupt);
        InterruptVo rsVo = new InterruptVo();
        if(StringTools.isEmpty(sessionId)||StringTools.isEmpty(autoInterrupt)){
            rsVo.setCode(-1);
            rsVo.setMsg("参数异常");
            if (StringUtil.isEmpty(jsonpCallBack))
                return JSONObject.toJSONString(rsVo).toString();

            return jsonpCallBack + "(" + JSONObject.toJSONString(rsVo).toString() + ")";
        }

        rsVo.setSessionId(sessionId);
        try {
            if (StringUtil.isEmpty(sessionId) || Constants.UN_DEFINED.equals(sessionId)) {
                rsVo.setCode(-1);
                rsVo.setMsg(Constants.LOCAL_EXCEPTION_7);
            } else {
                if (SampleMemoryCache.sessionInterruptMap.get(sessionId) != null
                        || redisTemplate.opsForValue().get(RedisKey.INTERRUPT_FAIL + sessionId) != null) { //防止重复操作

                    rsVo.setCode(-6);
                    rsVo.setMsg(Constants.LOCAL_MSG_DO_AGAIN);

                    if (StringUtil.isEmpty(jsonpCallBack))
                        return JSONObject.toJSONString(rsVo).toString();

                    return jsonpCallBack + "(" + JSONObject.toJSONString(rsVo).toString() + ")";
                }

                String redisSessionId = RedisKey.CALL_HISTORY_RPIX + sessionId;
                //中断操作记录入缓存
                if (autoInterrupt) { //自动中断 将操作保存到redis
                    redisTemplate.opsForHash().put(redisSessionId, RedisFields.INTERRUPT, Constants.AUTO_INTERRUPT.toString());
                } else { //手动中断
                    redisTemplate.opsForHash().put(redisSessionId, RedisFields.INTERRUPT, Constants.INTERRUPT.toString());
                }

                //中断时间
                redisTemplate.opsForHash().put(redisSessionId, RedisFields.INTERRUPTTIME, DateUtils.formatDate(new Date(), DateUtils.DATE_FORMAT_DATETIME_SSS));
                /*读取当前状态*/
                Map<String, String> callHistoryMap = redisTemplate.opsForHash().entries(redisSessionId);
                String rs = null;
                if (autoInterrupt) { //自动中断
                    /*中断*/
                    rs = todoInterruptCall(callHistoryMap.get(RedisFields.CALL_HISTORY_MESSAGE_ID));
                    /*中断成功*/
                    if (Constants.SUCCESS.equals(rs)) {

                        rsVo.setCode(1);
                        rsVo.setMsg(Constants.LOCAL_MSG_CALL_OVER);
                        logger.debug("interruptCall clickCallStop SUCCESS: autoInterrupt");
                        redisTemplate.opsForValue().set(RedisKey.INTERRUPT_FAIL + sessionId, "true", RedisTimeOut.CACHE_FROUR_HOUR, TimeUnit.MILLISECONDS);
                    } else {
                    /*中断失败*/
                        rsVo.setCode(-2);
                        rsVo.setMsg(Constants.LOCAL_MSG_INTERRUPTE_FAILED);
                        logger.debug("interruptCall clickCallStop FAIL: 中断失败");
                    }

                } else {//手动挂断

                  /*运营商未返回状态，表明未开始呼叫，则需延迟中断到主叫ring状态返回时。*/
                    /*中断*/
                    rs = todoInterruptCall(callHistoryMap.get(RedisFields.CALL_HISTORY_MESSAGE_ID));

                    if (Constants.SUCCESS.equals(rs))
                        redisTemplate.opsForValue().set(RedisKey.INTERRUPT_FAIL + sessionId, "true", RedisTimeOut.CACHE_FROUR_HOUR, TimeUnit.MILLISECONDS);

                     /*中断成功*/
                    if (Constants.SUCCESS.equals(rs)) {

                        /*正常通话，返回通话结束*/
                        rsVo.setCode(2);
                        rsVo.setMsg(Constants.LOCAL_MSG_CALL_OVER);
                        logger.debug("interruptCall clickCallStop SUCCESS: 手动");


                    } else {
                        /*中断失败*/
                        rsVo.setCode(-2);
                        rsVo.setMsg(Constants.LOCAL_MSG_INTERRUPTE_FAILED);
                        logger.debug("interruptCall clickCallStop SUCCESS: 中断失败:sessionId" + sessionId);
                    }

                }
            }

        } catch (Exception e) {
            e.printStackTrace();
            logger.error("invoking interruptCall failed:" + e.getMessage());
            rsVo.setCode(-3);
            rsVo.setMsg(Constants.LOCAL_EXCEPTION_3);
        }

        logger.debug("SampleMemoryCache.sessionInterruptMap：sessionId=" + sessionId + SampleMemoryCache.sessionInterruptMap.get(sessionId));

        if (StringUtil.isEmpty(jsonpCallBack))
            return JSONObject.toJSONString(rsVo).toString();

        return jsonpCallBack + "(" + JSONObject.toJSONString(rsVo).toString() + ")";
    }


    /**
     * 中断操作
     * @param callId
     * @return
     */

    public String todoInterruptCall(String callId) {
        try {
            //设置访问超时时间
            System.setProperty("sun.net.client.defaultConnectTimeout", "10000");
            System.setProperty("sun.net.client.defaultReadTimeout", "10000");
            //初始化acsClient暂时不支持多region
            IClientProfile profile = DefaultProfile.getProfile("cn-hangzhou", AliyunAkInfo.accessKeyId, AliyunAkInfo.accessKeySecret);
            DefaultProfile.addEndpoint("cn-hangzhou", "cn-hangzhou", AliyunAkInfo.product, AliyunAkInfo.domain);
            IAcsClient acsClient = new DefaultAcsClient(profile);
            //组装请求对象-CallId从上次呼叫调用的返回值中获取
            CancelCallRequest request = new CancelCallRequest();
            request.setCallId(callId);
            //hint 此处可能会抛出异常，注意catch
            CancelCallResponse cancelCallResponse = acsClient.getAcsResponse(request);
            if (StringTools.isEmpty(cancelCallResponse)) {
                return Constants.FAIL;
            }
            if ("OK".equals(cancelCallResponse.getCode())) {
                return Constants.SUCCESS;
            } else {
                logger.info("------------>中断失败，原因，code：{},msg:{},RequestId:{},callId:{}", cancelCallResponse.getCode(), cancelCallResponse.getMessage(), cancelCallResponse.getRequestId(), callId);
                return Constants.FAIL;
            }
        } catch (Exception e) {
            logger.error("中断异常：callId:{}", callId, e);
            return Constants.FAIL;
        }
    }


    /**
     * 阿里云呼入转接
     * @param vo
     * @return
     */
    @RequestMapping("/dynamicTrans")
    public Map<String,Object> dynamicTransNum(AliyunTransNumVo vo){
        logger.info("----------------->阿里云呼入转接请求参数转接param:{}",vo.toString());
        Map<String,Object> map = new HashMap<>();
        Map<String,Object> dataMap = new HashMap<>();

        if(StringTools.isEmpty(vo.getCaller_num())
                ||StringTools.isEmpty(vo.getCaller_show_num())
                ||StringTools.isEmpty(vo.getCall_id())){
            map.put("result", Constants.FAIL_STR);
            map.put("msg","缺少必要参数！");
            map.put("data",dataMap);
            return map;
        }

/*        if(!verificaParam(vo)){
            map.put("result", Constants.FAIL_STR);
            map.put("msg","ukey校验失败！");
            map.put("data",dataMap);
            return map;
        }*/

        String sessionId = UUIDs.base64UUID();
        vo.setSessionId(sessionId);


        try {
            String phone = aliyunTransNumBiz.AliyunTransNum(vo);
            dataMap.put("called_num",phone);
        }catch (Exception e){

            logger.error("呼入获取主显号异常，sessionId:{}",e);
            dataMap.put("called_num", "-1");

        }finally {

            map.put("result",Constants.SUCCESS_STR);
            map.put("msg","成功");
            // dataMap.put("called_show_num",vo.getCaller_show_num());
            dataMap.put("called_show_num","057128204523");
            dataMap.put("call_id",StringTools.isEmpty(vo.getCall_id())?"":vo.getCall_id());
            map.put("data",dataMap);
            //关联sessionId
            try{
                 redisTemplate.opsForValue().set(RedisKey.CALL_IN+vo.getCall_id(),sessionId, RedisTimeOut.CACHE_ONE_DAY, TimeUnit.SECONDS);
            }catch (Exception e){
                logger.error("aliyun call in write redis fali callId:{},sessionId:{}",vo.getCall_id(),sessionId);
            }
        }
        logger.info("-------------->阿里云呼入转接返回参数map：{}",map.toString());
        return map;
    }


    /**
     * 分析服务项目推送数据到客户端
     * @param sessionId
     * @param jsonStr
     * @return
     */
//    @RequestMapping("pushToBrowserBySessionId")
//    public String pushToBrowserBySessionId(String sessionId, String jsonStr, HttpServletRequest httpServletRequest){
//        try {
//
//            logger.info("获取分析服务推过来的数据sesionId：{},jsonStr:{}",sessionId,jsonStr);
//            Boolean bl = webSocketService.pushToBrowserBySessionId(sessionId, jsonStr);
//            if (bl)
//                return Constants.success;
//            else
//                return Constants.fail;
//        }catch (Exception e){
//            logger.error("推送语音分析结果失败sessionId:{},jsonStr:{}",sessionId,jsonStr,e);
//            return Constants.fail;
//        }
//    }

}

